package main

import (
	"database/sql"
	"fmt"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

// 定义一个全局对象db
var db *sql.DB

type user struct {
	id    int
	name  string
	email string
}

// 定义一个初始化数据库的函数
func initDB() (err error) {
	// DSN:Data Source Name
	dsn := "root:test123456@tcp(127.0.0.1:3306)/golang_gin_test"
	// 不会校验账号密码是否正确
	// 注意！！！这里不要使用:=，我们是给全局变量赋值，然后在main函数中使用全局变量db
	db, err = sql.Open("mysql", dsn)
	// 设置最大连接时长
	db.SetConnMaxLifetime(time.Minute * 3)
	// 设置最大连接数
	db.SetMaxOpenConns(10)
	// 空闲连接数
	db.SetMaxIdleConns(10)
	if err != nil {
		return err
	}
	// 尝试与数据库建立连接（校验dsn是否正确）
	err = db.Ping()
	if err != nil {
		return err
	}
	return nil
}

func queryOneRow() {
	var user user
	str := "select * from test where id = ?"
	err := db.QueryRow(str, 1).Scan(&user.id, &user.name, &user.email)
	if err != nil {
		panic(err)
	} else {
		fmt.Printf("u: %v", user)
	}
}

func queryMultiRow() {
	rows, err := db.Query("select * from test")
	if err != nil {
		fmt.Println("db operate failed, err:", err)
		return
	}
	defer rows.Close()

	// 循环读取结果集中的数据
	for rows.Next() {
		var u user
		err := rows.Scan(&u.id, &u.name, &u.email)
		if err != nil {
			fmt.Printf("scan failed, err:%v\n", err)
			return
		}
		fmt.Printf("id:%d name:%s age:%s\n", u.id, u.name, u.email)
	}
}

func insert(username, password string) {
	str := "insert into test values(?, ?)"
	r, err := db.Exec(str, username, password)
	if err != nil {
		fmt.Println("db exec error:", err)
		return
	} else {
		i, _ := r.LastInsertId()
		fmt.Println("i:", i)
	}
}

func update(_email, _id string) {
	str := "update test set email=? where id=?"
	r, err := db.Exec(str, _email, _id)
	if err != nil {
		fmt.Println("db exec error:", err)
		return
	} else {
		i, _ := r.RowsAffected()
		fmt.Println("i:", i)
	}
}

func delete() {
	str := "delete from test where id=?"
	r, err := db.Exec(str, "1")
	if err != nil {
		fmt.Println("err: ", err)
		return
	}
	rows, err := r.RowsAffected()
	if err != nil {
		fmt.Println("err: ", err)
		return
	}
	fmt.Println("删除成功, ", rows)
}

func main() {
	// 1. 连接数据库
	err := initDB() // 调用输出化数据库的函数
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}

	// 2.1 查询单行
	queryOneRow()
	// 2.2 查询多行
	queryMultiRow()

	// 3. 插入
	insert("mine", "123456")

	// 4. 更新
	update("1196010@qq.com", "1")

	// 5. 删除
	delete()
}
